package org.polyforms.repository.factory.support;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;

import org.polyforms.repository.factory.EntityClassResolver;
import org.polyforms.repository.strategy.EntityClassResolvingStrategy;

/**
 * Implementation of {@link EntityClassResolver} which uses Strategy pattern.
 * 
 * @author Kuisong Tong
 * @since 1.0
 */
@Named
public final class StrategicEntityClassResolver implements EntityClassResolver {
    private final Map<Class<?>, Class<?>> resolvedEntityClasses = new HashMap<Class<?>, Class<?>>();
    private final List<EntityClassResolvingStrategy> entityClassResolvingStrategies;

    /**
     * Create an instance with {@link EntityClassResolvingStrategy}s.
     */
    @Inject
    public StrategicEntityClassResolver(final List<EntityClassResolvingStrategy> entityClassResolvingStrategies) {
        this.entityClassResolvingStrategies = entityClassResolvingStrategies;
    }

    /**
     * {@inheritDoc}
     */
    public Class<?> resolve(final Class<?> repositoryClass) {
        if (resolvedEntityClasses.containsKey(repositoryClass)) {
            return resolvedEntityClasses.get(repositoryClass);
        }

        final Class<?> resolvedEntityClass = resolveFromStrategies(repositoryClass);
        resolvedEntityClasses.put(repositoryClass, resolvedEntityClass);
        return resolvedEntityClass;
    }

    private Class<?> resolveFromStrategies(final Class<?> repositoryClass) {
        for (final EntityClassResolvingStrategy entityClassResolvingStrategy : entityClassResolvingStrategies) {
            final Class<?> entityClass = entityClassResolvingStrategy.getEntityClass(repositoryClass);
            if (entityClass != null) {
                return entityClass;
            }
        }

        return null;
    }
}
